#include "c3a_sequence.h"

void c3a_ini_list(Code_list *cl)
{
	cl->top_list=0; /*LOOOOOOOOOOOL */
	cl->file_list=0;
	cl->read_list=0;
	cl->c3a_line=1;
}

void c3a_reset_line(Code_list *cl)
{
	cl->pos_inici = (cl->c3a_line)+1;
	cl->c3a_line=1;
}

int c3a_get_quad(Code_list *cl)
{
	return(cl->c3a_line);
}

int c3a_emet_unari(Code_list *cl, char dst[], char op[], char operan[])
{
  Node_c3a instr;

	if ((cl->top_list) < MAX_LINES_C3A)
	{
		sprintf(instr,"%i: \t %s := %s %s",cl->c3a_line, operan, dst, op );
		cl->c3a_line = cl->c3a_line + 1;
		sprintf(cl->codi[cl->top_list],"%s",instr); 
		(cl->top_list)++;
		return 0;
	}
	else return -1;
}

int c3a_emet_binari(Code_list *cl, char dst[],char op[], char operan1[], char operan2[])
{
  Node_c3a instr;

	
	if ((cl->top_list) < MAX_LINES_C3A)
	{
		sprintf(instr,"%i:\t %s := %s %s %s",cl->c3a_line, dst, operan1,op, operan2);
		cl->c3a_line = cl->c3a_line +1;
		sprintf(cl->codi[cl->top_list],"%s",instr); 
		(cl->top_list)++;
		return 0;
	}
	else return -1;
}

int c3a_emet_instr(Code_list *cl, char cadena[])
{
  Node_c3a instr;

	sprintf(instr,"%i:\t %s",cl->c3a_line, cadena);

	if ((cl->top_list) < MAX_LINES_C3A)
	{
		
		sprintf(cl->codi[cl->top_list],"%s",instr); 
		cl->c3a_line = cl->c3a_line +1;
		(cl->top_list)++;
		return cl->c3a_line;
	}
	else return -1;
}


int c3a_emet_comen(Code_list *cl, char cadena[])
{
  Node_c3a instr;

	sprintf(instr,"%s",cadena);

	if ((cl->top_list) < MAX_LINES_C3A)
	{
		cl->c3a_line = cl->c3a_line +1;
		sprintf(cl->codi[cl->top_list],"%s",instr); 
		(cl->top_list)++;
		return 0;
	}
	else return -1;
}


int c3a_back_patching(Code_list *cl, int lineToInsert, int number)
{

	Node_c3a new_instr;
	Node_c3a instr;

	sprintf(instr,"%s",cl->codi[lineToInsert-1]);
	sprintf(new_instr,"%s %i",instr,number);
	
	sprintf(cl->codi[lineToInsert-1],"%s",new_instr);
	/*cocatenar amb la cadena pasada*/
	sprintf(cl->codi[lineToInsert-1],"%s",new_instr);
	return(lineToInsert);


}

/* Introduce a new C3A to the code queue
   it returns 0 if the insertion is complete
 and -1 if the heap (list) is full
*/
int c3a_input_queue(Code_list *cl, Node_c3a instr)
{
	if ((cl->top_list) < MAX_LINES_C3A)
	{
		sprintf(cl->codi[cl->top_list],"%s",instr); 
		(cl->top_list)++;
		return 0;
	}
	else return -1;

}

/* Read a C3A of the code queue indicated by read index
   it returns the index number if the read is complete
   and -1 if the read index is equal write index
*/
int c3a_output_queue(Code_list *cl, Node_c3a instr)
{
	if ((cl->read_list) < (cl->top_list))
	{
		sprintf(instr,"%s", cl->codi[(cl->read_list)]);
		(cl->read_list)++;
		return((cl->read_list)-1);
	}
	return(-1);
}

/* Read a C3A of the code queue indicated by an index
   it returns the index number if the read is complete
   and -1 if the index is greater than top_pointer
*/
int c3a_output_queue_index(Code_list *cl,int index ,Node_c3a instr)
{
	if (index < (cl->top_list))
	{
		sprintf(instr,"%s", cl->codi[index]);
		return(index);
	}
	return(-1);	
}

int c3a_concatenate(Code_list *cl,int index, char cadena[])
{
	Node_c3a instr;
	
	if (index < (cl->top_list))
	{
		sprintf(instr,"%s", cl->codi[index]);
		/*cocatenar amb la cadena pasada*/
		sprintf(cl->codi[index],"%s",instr);
		return(index);
	}
	return(-1);
}
int c3a_has_mores_elements(Code_list *cl)
{
	if ((cl->read_list) < (cl->top_list)) {return (1);}
	else return (0);
}

void c3a_reset_towrite(Code_list *cl)
{
	cl->file_list = 0;
}	

int c3a_has_mores_elements_towrite(Code_list *cl)
{
	if ((cl->file_list) < (cl->top_list)) {return (1);}
	else return (0);
}

int c3a_get_instr_towrite(Code_list *cl,Node_c3a instr)
{

	sprintf(instr,"%s",cl->codi[cl->file_list]);
	
	(cl->file_list)++;
	return(0);
}
	
void c3a_print(Code_list *cl)
{
  Node_c3a instr;
  
  	c3a_reset_towrite(cl);
  
    printf(" ******** C3A Generat ******** \n");
	while (c3a_has_mores_elements_towrite(cl))
	{
		c3a_get_instr_towrite(cl,instr);
		printf("%s\n",instr); 				
	}
	printf(" ***************************** \n");
	
}

int c3a_write_out(Code_list *cl, char nom_arxiu[])
{
  Node_c3a instr;
  FILE *fout;
  
    fout = fopen(nom_arxiu,"w");
    if (fout== NULL) {return -1;}
  	c3a_reset_towrite(cl);
  
    fprintf(fout," ******** C3A Generat ******** \n");
	while (c3a_has_mores_elements_towrite(cl))
	{
		c3a_get_instr_towrite(cl,instr);
		fprintf(fout,"%s\n",instr); 				
	}
	fprintf(fout," ***************************** \n");
	return(0);
}

/*-------------------------------- Llistes ------------------------*/
/*------------------------- Llistes int ---------------------------*/
void c3a_reset_list(Tlist *ll)
{
	ll->num = 0;
}

void c3a_insert_list(Tlist *ll, int elem)
{
	ll->llista[ll->num] = elem;
	ll->num = ll->num + 1;
}

void c3a_fusionar_list (Tlist *dst, Tlist *src)
{
	int num;
	int i;
	int elem;

	num = src->num;

	for (i=0; i<num; i++)
		{
		elem = src->llista[i];
		c3a_insert_list(dst,elem);
		}
}
int c3a_get_elements(Tlist *ll)
{
 return(ll->num);
}

int c3a_get_elemAt(Tlist *ll, int index)
{
  return(ll->llista[index]);
}

/*-------------------------- Llistes binaries------------------------*/
void c3a_reset_bin_list(Tlist *ll)
{
	ll->num = 0;
}

void c3a_insert_bin_list(Tlist_binary *ll,char value[], int line)
{
 

	sprintf(ll->llista[ll->num].value,"%s",value);
 	ll->llista[ll->num].linia = line;

	ll->num = ll->num + 1;
}

void c3a_fusionar_bin_list(Tlist_binary *dst, Tlist_binary *src)
{
 char value[20];
 int line;
 int num;
 int i;

	num = src->num;
	for (i=0; i< num; i++)
		{
			c3a_get_elem_bin_list(src, value, &line, i);
			c3a_insert_bin_list(dst,value,line);
		}
	
}

int c3a_get_elements_bin_list(Tlist_binary *ll)
{
	return(ll->num);
}

void c3a_get_elem_bin_list(Tlist_binary *ll, char value[], int *line, int index)
{
 int linia;

 sprintf(value,"%s",ll->llista[index].value);
 linia = ll->llista[index].linia;

 *line = linia;
}
